package cz.possoft.client.four.gui.components;

import java.awt.Color;
import java.awt.Graphics;

import cz.possoft.client.gui.gamepanel.components.GamePane;
import cz.possoft.generic.utils.GenericUtils;
import cz.possoft.serializable.four.game.FourPole;
import cz.possoft.serializable.generic.HraciPole;
import cz.possoft.serializable.generic.Location;

/**
  * Vizualni hraci pole pro hru Four
  * 
  * @author mara
  */
public class FourPane extends GamePane implements Runnable {		
	
	// misto kde se nachazi oznacena figurka prstencem.
	Location ringFigurkaLocation = new Location(-1, -1);
	
	// indikator, zda je prave vlakno spusteno. Pouzity pro mizeni i objevovani
	private boolean runFlag = false;	
	
	// vlakno patrici k tomuto chessPane
	private Thread thisThread;
	
	// count je pocet pixelu pri vykresleni (padani) ksichtu
	// pocatek padani je bod, kde zacina figurka padat
	// sleep_interval je interval pri padani 
	private static final int COUNT = 20;
	private static final int POCATEK_PADANI = 0;
	private static final int SLEEP_INTERVAL = 30; 
	
	// souradnice pouzite pri padani ksichtu. xCil a yCil jsou zaverecne, kam ma ksicht spadnout
	// xWork a yWork jsou prubezne
	private int xCil = -100;
	private int yCil = -100;
	private int xWork = -100;
	private int yWork = -100;
	private int colorWork = GenericUtils.COLOR_NEUTRAL;
	
	// Misto, na ktere prave pada balonek. Na tomto miste se nebude kreslit
	private Location dontPaintLocation = new Location(-1, -1).setNull();
	
	// java reflection
    public FourPane() {    	
    }    
    
    // nasetuje hraci pole a provede dalsi inicializacni akce,
    // nakresleni atd.
    public void init(HraciPole hPole) {  
    	thisThread = new Thread(this);
    	thisThread.start();
    	addMouseMotionListener(new FourMouseMotionListener());
    	addMouseListener(new FourMouseListener());
    	setHraciPole(hPole);
    }    
    
    // Nakresleni sachovnice     
    public void paint(Graphics g)  {
     super.paint(g);
     g.setColor(Color.BLUE);
     g.fillRect(0,0,450,450);
     for (int i=0 ; i<7 ; i++)
    	 for (int j=0 ; j<7 ; j++) {
    		 paintFigurka(i,j,g);
    	 } 
     // pripad, kdy prave pada ksicht
     if (xCil != -100) {    	   		 
    	    paintKsicht(xWork, yWork, colorWork, g);
     }
   }   
    
    // nakresli jednu figurku (ctverecek) v hracim poli na 
    // specifikovanych souradnicich.
    private void paintFigurka(int x, int y, Graphics g) {
    	if (y > 0) {
    		g.setColor(Color.BLACK);
    	}
    	else {
    	    g.setColor(Color.DARK_GRAY);
    	}
    	// figurky z vitezne rady obarvime svetle zelene
    	if (((FourPole)getHraciPole()).getFigurka(x, y).isPartOfWinningLine()) {
    		g.setColor(new Color(160, 255, 160));
    	}

    	// zkousime jestli se nejedna figurku, na kterou prave pada balonek
    	boolean dontPaintFlag = false;
    	if ((dontPaintLocation.getX() == x) && (dontPaintLocation.getY() == y)) {
    		g.setColor(Color.BLACK);
    		dontPaintFlag = true;
    	}
    	int xx = getXForPaint(x);
    	int yy = getYForPaint(y);
    	g.fillRect(xx, yy, 63, 63);
    	if (!dontPaintFlag) {
    	    paintKsicht(xx, yy, ((FourPole)getHraciPole()).getFigurka(x, y).getColor(), g);
    	}
    	
	    // misto oznacene pro spusteni balonku
	    if ((ringFigurkaLocation.getX() == x) && (ringFigurkaLocation.getY() == y)) {
	    	g.setColor(Color.RED);
	    	g.drawRect(xx+1, yy+1, 61, 61);
	    	g.drawRect(xx+2, yy+2, 59, 59);
	    }    		    
	    g.setColor(Color.GRAY); 	    
    	g.drawRect(xx, yy, 63, 63);
    }
    
    // nakresli ksicht se stredem v bode x,y. Barva je bud bila nebo cerna(cervena nebo modra)
    private void paintKsicht(int x, int y, int color, Graphics g) {
    	if (color == GenericUtils.COLOR_NEUTRAL) {
    		return;
    	}
    	if (color == GenericUtils.COLOR_WHITE) {
    	    g.setColor(Color.RED);	
    	}
    	else {
    		g.setColor(Color.BLUE);
    	}
    	g.fillArc(x , y , 63, 63, 0, 360);
    	// huba a oci
    	g.setColor(Color.DARK_GRAY);    	
    	g.drawArc(x + 16, y + 18, 30, 30, 200, 140);    	
    	g.drawArc(x + 13, y + 17, 15, 8, 0, 360);
    	g.drawArc(x + 36, y + 17, 15, 8, 0, 360);
    	// vnitrek oci
    	g.fillArc(x + 19, y + 17, 5, 9, 0, 360);
    	g.fillArc(x + 42, y + 17, 5, 9, 0, 360);
    }
    
	// Vraci bod, kde se zacina kreslit pro lokaci X na sachovnici z intervalu
	// 0-6.	
	private int getXForPaint(int x) {		
		return 4 + x * 63;		
	}

	// Vraci bod, kde se zacina kreslit pro lokaci Y na sachovnici z intervalu
	// 0-6.	
	private int getYForPaint(int y) {		
		return 4 + y * 63;		
	}

	public Location getRingFigurkaLocation() {
		return ringFigurkaLocation;
	}

	public void setRingFigurkaLocation(Location ringFigurkaLocation) {
		this.ringFigurkaLocation = ringFigurkaLocation;
	}    
	
	// metoda run bezi stale, ale priznak runFlag je true jen pokud se prave
	// prekresluje (pada) ksichtik
	public void run() {		
		while (true) {							
					try {
						// sleep 200 pokud je vlakno neaktivni - neprobiha mizeni nebo objevovani figurky						
						//Thread.sleep(200);
						synchronized(thisThread) {
						      thisThread.wait();
						}
					} catch (Exception e) {
						e.printStackTrace();
					}			        
					while (runFlag) {	
												
						try {
							// sleep 15 pokud je vlakno aktivni - probiha mizeni nebo objevovani figurky	
							Thread.sleep(SLEEP_INTERVAL);
						} catch (Exception e) {
							e.printStackTrace();
						}
						if (runFlag) {
							// pricitani k padani ksichtu
							yWork = yWork + COUNT;
							if (yWork >= yCil) {
								yWork = yCil;								
								xCil = -100;
								yCil = -100;
								dontPaintLocation.setNull();
								runFlag = false;
							}							
							repaint();
						}						
					}
		}
	}
	
	// nastartuje padani ksichtu, ktere skonci na sachovnici na souradnicich x,y
	public void startPadani(int x, int y, int color) {
		dontPaintLocation.setX(x);
		dontPaintLocation.setY(y);
		xCil = getXForPaint(x);
		yCil = getYForPaint(y);
		colorWork = color;
		xWork = xCil;
		yWork = POCATEK_PADANI;
		runFlag = true;
		synchronized(thisThread) {
		     thisThread.notify();
		}		
	}

}
